import { Byte } from "./libs/byte/byte";
import { getParseObj } from "./ProtoDef";

export module ProtoMod {
    /**
     * 协议请求的接口
     */
    export interface IProtoReq {
        protoid: number;
        read(b): void;
    }

    /**
     * 协议返回的接口
     */
    export interface IProtoRevc {
        protoid: number;
        write(b): void;
    }

    /**
     * 消息拆包
     * @param data 字节流数据
     */
    export function unPack(data: Buffer): IProtoReq|null {
        try{
            let byte = new Byte();
            byte.endian = Byte.BIG_ENDIAN;
            byte.writeArrayBuffer(data);
            byte.pos = 0;

            let cmdID = byte.readUint16();
            let dataLen = byte.getUint32();

            // 协议数据段
            let protoUint8Arr = byte.getUint8Array(byte.pos, dataLen);
            let protoByte = new Byte();
            protoByte.writeArrayBuffer(protoUint8Arr.buffer);
            protoByte.pos = 0;
            protoByte.endian = Byte.BIG_ENDIAN;

            // 解析请求数据
            let obj: IProtoReq = getParseObj(cmdID) as IProtoReq;
            obj?.read(protoByte);
            protoByte.clear();
            byte.clear();
            return obj;
        }catch (e){
            return null;
        }
    }

    /**
     * 消息封包
     * @param msg
     */
    export function pack(msg: IProtoRevc): Buffer {
        let data = new Byte(); // 优化,不要NEW 字节流对象!!!!!!!!!
        data.pos = 0;
        data.endian = Byte.BIG_ENDIAN;

        msg.write(data);
        let cmd = msg.protoid;

        // 消息域
        let msgByteArr = new Byte(); // 优化,不要NEW 字节流对象!!!!!!!!!
        msgByteArr.pos = 0;
        msgByteArr.endian = Byte.BIG_ENDIAN;

        // msgid(2字节) + msg(长度4字节) + msgData(消息数据)
        msgByteArr.writeUint16(cmd);
        msgByteArr.writeUint32(data.length);

        if (data.length > 0) {
            msgByteArr.writeArrayBuffer(data.buffer);
        }
        return Buffer.from(msgByteArr.buffer);
    }

}

